import { defineComponent, ref, Ref, onMounted } from 'vue';
import { IParam, Util } from 'ibz-core';
const AppAnchorProps = {
  /**
   * @description 传入锚点集合
   * @type {Array}
   */
  anchors: {
    type: Array,
  },
  /**
   * @description 滚动容器标识
   * @type {String}
   */
  scrollContainerTag: {
    type: String,
    default: '',
  },
};

/**
 * @description 锚点组件
 */
export const AppAnchorComponent = defineComponent({
  name: 'AppAnchor',
  props: AppAnchorProps,
  /**
   * @description 设置响应式
   * @param {*} props 传入参数
   * @return {*}
   */
  setup(props: any) {
    /**
     * @description 选中锚点
     * @memberof AppAnchorComponent
     */
    const select: Ref<string> = ref('');

    /**
     * @description 滚动容器
     * @memberof AppAnchorComponent
     */
    const scrollContainer = ref({});

    /**
     * @description 锚点集合
     * @memberof AppAnchorComponent
     */
    const anchorList: any = ref([]);

    /**
     * @description 部件挂载
     * @memberof AppAnchorComponent
     */
    onMounted(() => {
      const { scrollContainerTag } = props;
      const _scrollContainer = document.querySelector(`.${scrollContainerTag}`);
      if (_scrollContainer) {
        scrollContainer.value = _scrollContainer;
        (_scrollContainer as any).getScrollElement().then((element: any) => {
          initAnchorList(element);
          element.addEventListener('scroll', (e: any) => {
            handleScroll(element);
          });
        });
      }
    });

    /**
     * @description 初始化锚点集合
     * @param {*} element 滚动容器对象
     * @memberof AppAnchorComponent
     */
    const initAnchorList = (element: any) => {
      const { anchors } = props;
      if (anchors.length > 0) {
        const height = element.scrollHeight;
        anchors.forEach((anchor: IParam) => {
          const _anchor = Util.deepCopy(anchor);
          const anchorEle = document.querySelector(`.${anchor.className}`);
          if (anchorEle) {
            //  计算滚动范围
            const rect = anchorEle.getBoundingClientRect();
            Object.assign(_anchor, {
              start: rect.top / height,
              end: rect.bottom / height,
              scrollTop: rect.top,
            });
          }
          anchorList.value.push(_anchor);
        });
      }
    };

    /**
     * @description 处理滚动事件
     * @param {HTMLElement} element 滚动容器对象
     * @memberof AppAnchorComponent
     */
    const handleScroll = (element: HTMLElement) => {
      const { scrollTop, offsetHeight, scrollHeight } = element;
      const slidingPer = scrollTop / (scrollHeight - offsetHeight);
      //  获取在其滚动范围中的锚点
      const selectAnchor = anchorList.value.find((anchor: IParam) => {
        return slidingPer >= anchor.start && slidingPer <= anchor.end;
      });
      if (selectAnchor) {
        select.value = selectAnchor.codeName;
      } else {
        select.value = '';
      }
    };

    /**
     * @description 点击锚点
     * @param {IParam} anchor 锚点
     * @param {*} event 源事件对象
     */
    const anchorClick = (anchor: IParam, event: any) => {
      event.stopPropagation();
      const element = document.querySelector(`.${anchor.className}`);
      if (element) {
        select.value = anchor.codeName;
        const _scrollContainer: any = scrollContainer.value;
        if (_scrollContainer && _scrollContainer.scrollToPoint && _scrollContainer.scrollToPoint instanceof Function) {
          _scrollContainer.scrollToPoint(0, anchor.scrollTop);
        }
      }
    };

    /**
     * @description 渲染部件
     * @return {*}
     */
    const render = () => {
      return (
        <div class='app-anchor'>
          {anchorList.value.map((anchor: IParam, index: number) => {
            return (
              <div
                class={['anchor-item', select.value === anchor.codeName ? 'is-select' : '']}
                key={index}
                onClick={(event: any) => anchorClick(anchor, event)}
              >
                <span class='caption'>{anchor.caption}</span>
              </div>
            );
          })}
        </div>
      );
    };
    return () => render();
  },
});
